<?php

namespace Modules\transactionwallet\Services;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Throwable;

class CryptoConvertService
{

    public function swapCryptoToEur(float $amountCrypto, string $crypto = 'bitcoin'): ?float
    {
        try {
            // ✅ Cache 5 secondes
            $prices = Cache::remember("crypto_prices_{$crypto}", 10, function () use ($crypto) {
                $response = Http::get('https://api.coingecko.com/api/v3/simple/price', [
                    'ids' => $crypto,
                    'vs_currencies' => 'usd,eur',
                ]);

                if ($response->failed()) {
                    Log::warning("CoinGecko API failed for swap {$crypto}");
                    return null;
                }

                return $response->json()[$crypto] ?? null;
            });

            if (!$prices) {
                return null;
            }

            $priceUsd = $prices['usd'] ?? null;
            $priceEur = $prices['eur'] ?? null;

            if (!$priceUsd || !$priceEur) {
                return null;
            }

            // Conversion logique
            $usdToEurRate = $priceEur / $priceUsd;

            // Valeur du swap
            $totalEur = $priceEur * $amountCrypto;

            return $totalEur;

        } catch (Throwable $th) {
            Log::error("swapCryptoToEur error: " . $th->getMessage());
            return null;
        }
    }

    public function cryptoUSDConvert($amount, $crypto = 'bitcoin', $currency = 'usd')
    {
        try {
            $amountUsd = $amount;
            $cacheKey = "crypto_usd_price_{$crypto}_{$currency}";

            // 🔒 1. Vérifie si déjà en cache (valide 3 min)
            $cryptoPrice = $this->cryptoPrice($cacheKey, $crypto, $currency);

            // 2. Si API rate limité → on garde dernière valeur
            if (empty($cryptoPrice) || $cryptoPrice <= 0) {
                $cachedValue = Cache::get($cacheKey . '_last');
                if ($cachedValue) {
                    Log::info("Using last cached value for {$crypto}");
                    $cryptoPrice = $cachedValue;
                } else {
                    return 0;
                }
            } else {
                Cache::put($cacheKey . '_last', $cryptoPrice, now()->addMinutes(3));
            }

            return $amountUsd / $cryptoPrice;

        } catch (Throwable $th) {
            Log::error("cryptoUSDConvert error: " . $th->getMessage());
            return 0;
        }
    }

    public function cryptoPrice(string $cacheKey, string $crypto = 'bitcoin', $currency = 'usd')
    {
        return Cache::remember($cacheKey, now()->addMinutes(3), function () use ($crypto, $currency) {
                $response = Http::get('https://api.coingecko.com/api/v3/simple/price', [
                    'ids' => $crypto,
                    'vs_currencies' => $currency,
                ]);

                if ($response->failed()) {
                    Log::warning("CoinGecko API failed for {$crypto}");
                    return null;
                }

                $data = $response->json();
                return $data[$crypto][$currency] ?? null;
            });
    }

    public function currencyConverter(string $from, string $to, float $amount): float
    {
        $cacheKey = 'fx:usd_eur:' . number_format($amount, 2, '.', '');
        #$fallbackRate = 1.08;

        Cache::forget($cacheKey);
        return Cache::remember($cacheKey, now()->addMinutes(10), function () use ($from, $to, $amount) { #$fallbackRate
            try {
                $response = Http::timeout(5)
                    ->retry(2, 200)
                    ->get('https://api.frankfurter.app/latest', [
                        'amount' => $amount,
                        'from'   => $from, //'USD',
                        'to'     => $to,  //'EUR',
                    ])
                ->throw();

                $eur = (float) data_get($response->json(), "rates.{$to}");
                return round($eur, 2); #$eur > 0 ? round($eur, 2) : round($amount * $fallbackRate, 2);
            } catch (\Throwable $e) {
                throw $e;
                // fallback en cas d’erreur API
                #return round($amount * $fallbackRate, 2);
            }
        });
    }

}
